package com.hbwxz.oauth2.config;

import com.hbwxz.oauth2.service.UserDetailServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * WebSecurityConfig
 *
 * @author shenzw
 * @date 2023/8/24
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailServiceImpl userService;

    /**
     * AuthenticationManager 这个东西怎么进行自动装配注入呢？
     *
     * @return AuthenticationManager
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 我上边这个方法太拉垮了，你直接用 super 的 authenticationManagerBean 方法，有点 low，
     * 我们高级着呢，我们控制 super.authenticationManagerBean() 方法中所使用的 AuthenticationManagerBuilder deleteBuilder
     *
     * @param auth the {@link AuthenticationManagerBuilder} to use
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService)
                .passwordEncoder(new PasswordEncoder() {
                    @Override
                    public String encode(CharSequence rawPassword) {
                        return new BCryptPasswordEncoder().encode(rawPassword);
                    }

                    @Override
                    public boolean matches(CharSequence rawPassword, String encodedPassword) {
                        return new BCryptPasswordEncoder().matches(rawPassword, encodedPassword);
                    }
                });
    }

    /**
     * 跨域问题 cors，csrf
     *
     * @param http the {@link HttpSecurity} to modify
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and().httpBasic()
                .and().cors()
                .and().csrf()
                .disable();

        // 为什么 disable csrf，spring security 引入了csrf，默认是开启的，csrf 和 rest（post）有冲突，所以基于目前我们大部分都是走的 rest 的 post 访问，所以需要disable；
        // csrf 默认支持：GET/HEAD/TRACE/OPTIONS，不支持 post
    }


    /**
     * 所有的访问都需要 oauth2 验证吗？api-doc，swagger，过滤点东西
     */
    @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/swagger-*");
    }

}
